/**
 @file sys_usw_mirror.h

 @date 2009-10-21

 @version v2.0

*/

#ifndef _SYS_USW_MIRROR_H
#define _SYS_USW_MIRROR_H
#ifdef __cplusplus
extern "C" {
#endif

/****************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"

#include "ctc_const.h"
#include "ctc_mirror.h"
#include "ctc_debug.h"

/****************************************************************
*
* Defines and Macros
*
****************************************************************/

#define SYS_MIRROR_ACLLOG_SESSION_RSV   8
#define SYS_MIRROR_CPU_SESSION_RSV      2

#define SYS_MIRROR_L2SPAN_SESSION       0
#define SYS_MIRROR_L3SPAN_SESSION       1
#define SYS_MIRROR_ACLLOG_SESSION       2
#define SYS_MIRROR_CPU_SESSION          SYS_MIRROR_ACLLOG_SESSION + SYS_MIRROR_ACLLOG_SESSION_RSV
#define SYS_MIRROR_IPFIX_LOG_SESSION    SYS_MIRROR_CPU_SESSION + SYS_MIRROR_CPU_SESSION_RSV
#define MAX_CTC_MIRROR_SESSION_TYPE     SYS_MIRROR_IPFIX_LOG_SESSION

#define MAX_SYS_MIRROR_SESSION_TYPE (MAX_CTC_MIRROR_SESSION_TYPE + 8)



#define MIRROR_LOCK \
            if (p_usw_mirror_master[lchip]->p_mutex) sal_mutex_lock(p_usw_mirror_master[lchip]->p_mutex)
#define MIRROR_UNLOCK \
            if (p_usw_mirror_master[lchip]->p_mutex) sal_mutex_unlock(p_usw_mirror_master[lchip]->p_mutex)


#define SYS_MIRROR_DISCARD_CHECK(flag) \
    if (0 == (flag & (CTC_MIRROR_IPFIX_DISCARD | \
                      CTC_MIRROR_ACLLOG_PRI_DISCARD | \
                      CTC_MIRROR_L3SPAN_DISCARD | CTC_MIRROR_L2SPAN_DISCARD))) \
        return CTC_E_INVALID_PARAM

#define SYS_MIRROR_DBG_OUT(level, FMT, ...)                          \
    do                                                     \
    {                                                      \
        CTC_DEBUG_OUT(mirror, mirror, MIRROR_SYS, level, FMT, ##__VA_ARGS__);  \
    } while (0)

enum sys_mirror_dest_data_type_e
{
    SYS_MIRROR_RSPAN_OVER_VLAN = 0,
    SYS_MIRROR_RSPAN_OVER_MCAST,
    SYS_MIRROR_SPAN_OVER_LINKAGG,
    SYS_MIRROR_RSPAN_OVER_LINKAGG,
    SYS_MIRROR_RSPAN_OVER_ILOOP
};
typedef enum sys_mirror_dest_data_type_e sys_mirror_dest_data_type_t;

struct sys_mirror_dest_node_s
{
    /*key*/
    uint32 session_id   :4;     /* session id */
    uint32 type         :5;     /* mirror type */
    uint32 dir          :1;     /* direction */
    uint32 member_index :3;     /* member index */
    uint32 rsv          :19;
    /*data*/
    uint32 nh_id;               /* rspan over vlan; rspan over mcast nh */
    uint32 loop_port    :16;    /* rspan over mcash nh */
    uint32 linkagg_id   :10;    /* span over linkagg */
    uint32 data_type    :3;     /* 0: rspan over vlan; 1: rspan over mcast; 2: span over linkagg; 3: rspan over vlan and linkagg */
    uint32 rsv2         :3;
};
typedef struct sys_mirror_dest_node_s sys_mirror_dest_node_t;

struct sys_mirror_master_s
{
    sal_mutex_t* p_mutex;
    ctc_hash_t* dest_hash;
};
typedef struct sys_mirror_master_s sys_mirror_master_t;


/****************************************************************************
*
* Function
*
*****************************************************************************/
extern int32
sys_usw_mirror_init(uint8 lchip);

extern int32
sys_usw_mirror_set_port_en(uint8 lchip, uint32 gport, ctc_direction_t dir, bool enable, uint8 session_id);

extern int32
sys_usw_mirror_get_port_info(uint8 lchip, uint32 gport, ctc_direction_t dir, bool* enable, uint8* session_id);

extern int32
sys_usw_mirror_set_vlan_en(uint8 lchip, uint16 vlan_id, ctc_direction_t dir, bool enable, uint8 session_id);

extern int32
sys_usw_mirror_get_vlan_info(uint8 lchip, uint16 vlan_id, ctc_direction_t dir, bool* enable, uint8* session_id);

extern int32
sys_usw_mirror_set_dests(uint8 lchip, ctc_mirror_dest_t* mirror);

extern int32
sys_usw_mirror_rspan_escape_en(uint8 lchip, bool enable);

extern int32
sys_usw_mirror_rspan_escape_mac(uint8 lchip, ctc_mirror_rspan_escape_t* escape);

extern int32
sys_usw_mirror_unset_dests(uint8 lchip, ctc_mirror_dest_t* mirror);

extern int32
sys_usw_mirror_set_mirror_discard(uint8 lchip, ctc_direction_t dir, uint16 discard_flag, bool enable);

extern int32
sys_usw_mirror_get_mirror_discard(uint8 lchip, ctc_direction_t dir, ctc_mirror_discard_t discard_flag, bool* enable);

extern int32
sys_usw_mirror_set_erspan_psc(uint8 lchip, ctc_mirror_erspan_psc_t* psc);

extern int32
sys_usw_mirror_show_info(uint8 lchip, ctc_mirror_info_type_t type, uint32 value);

extern int32
sys_usw_mirror_deinit(uint8 lchip);

extern void
sys_usw_mirror_type_mapping(uint8 ctc_type, uint8 acl_prio, uint8* sys_type);

extern void
sys_usw_mirror_type_unmapping(uint8 sys_type, uint8* ctc_type, uint8* acl_prio);

extern int32
sys_usw_mirror_mapping_excp_index(uint8 lchip, ctc_mirror_dest_t* mirror, uint32* p_out_idx, uint8 pos);

#ifdef __cplusplus
}
#endif

#endif

